﻿using HsServerHa.Common.Auth;
using HsServerHa.Entity.Models;
using HsServerHa.Utility.DataHelper;
using HsServerHa.Utility.NetWork;
using HsServerHa.Utility.SQLite;
using Newtonsoft.Json.Linq;
using Quartz;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace HsServerHa.Jobs
{
    /// <summary>
    /// 该属性告诉Quartz不要同时执行给定Job定义
    /// </summary>
    [DisallowConcurrentExecution]
    public class CheckFilesSyncTaskJob : IJob
    {
        public static  List<FileSystemWatcher> fileSystemWatcherList = new List<FileSystemWatcher>();

        public static bool IsStart=false;
        public async Task Execute(IJobExecutionContext context)
        {
            #region 授权验证
            if (!AuthorizationVerification.IsVerification())
            {
                return;
            }
            #endregion 
            return;
            if (App.isMaster!=null)
            {
                if (IsStart)
                {
                    return;
                }
                var list = await SQLiteHelper.TableAsync<FilesSyncManageEntity>().Where(x=>x.IsEnable=="是").ToListAsync().ConfigureAwait(false);
                var filesFirst = list.FirstOrDefault();
                var listXt = await SQLiteHelper.TableAsync<HeartEntity>().Where(x => x.IsLocal == "true").ToListAsync().ConfigureAwait(false);
                var xtFirst = listXt?.FirstOrDefault();

                if (filesFirst != null&& xtFirst!=null)
                {
                    if (xtFirst.HeartIP==null||xtFirst.MasterHeartIPBind==null)
                    {
                        return;
                    }
                   IsStart= true;
           
                    TcpListener listener = new TcpListener(IPAddress.Parse(xtFirst.HeartIP), 21);
                    listener.Start();

                    string sourceServer = $"{xtFirst.HeartIP}";
                    string destServer = $"{xtFirst.MasterHeartIPBind}";
                    string username = "username";
                    string password = "password";
                    string sourcePath = $@"{filesFirst.FilePath}"; // 源文件夹路径
                    string destPath = $@"{filesFirst.FilePath}"; // 目标文件夹路径
                    int syncIntervalSeconds = 5; // 同步间隔时间（秒）
                    if (App.isMaster.Value)
                    {
                 
                    }
                    else
                    {
                     
                    }
                    Task.Run(async() => {
                        while (true)
                        {
                            TcpClient client = listener.AcceptTcpClient();
                            Console.WriteLine("Client connected");

                            NetworkStream stream = client.GetStream();
                            StreamReader reader = new StreamReader(stream, Encoding.ASCII);
                            StreamWriter writer = new StreamWriter(stream, Encoding.ASCII) { AutoFlush = true };

                            writer.WriteLine("220 Service ready");

                            string username = null;
                            string password = null;

                            while (true)
                            {
                                string request = reader.ReadLine();
                                Console.WriteLine("Command: " + request);

                                if (request.StartsWith("USER"))
                                {
                                    username = request.Substring(5);
                                    writer.WriteLine("331 User name okay, need password");
                                }
                                else if (request.StartsWith("PASS"))
                                {
                                    password = request.Substring(5);
                                    writer.WriteLine("230 User logged in");
                                    break;
                                }
                                else
                                {
                                    writer.WriteLine("530 Not logged in");
                                }
                            }

                            while (true)
                            {
                                string request = reader.ReadLine();
                                Console.WriteLine("Command: " + request);

                                if (request.StartsWith("PWD"))
                                {
                                    writer.WriteLine("257 \"/\" is current directory");
                                }
                                else if (request.StartsWith("CWD"))
                                {
                                    string directory = request.Substring(4);
                                    // Change current directory logic
                                    writer.WriteLine("250 Directory changed to " + directory);
                                }
                                else if (request.StartsWith("TYPE"))
                                {
                                    writer.WriteLine("200 Type set to " + request.Substring(5));
                                }
                                else if (request.StartsWith("PASV"))
                                {
                                    // Enter passive mode logic
                                    writer.WriteLine("227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)");
                                }
                                else if (request.StartsWith("LIST"))
                                {
                                    // List directory contents logic
                                    writer.WriteLine("150 Here comes the directory listing");
                                    writer.WriteLine("226 Directory send OK");
                                }
                                else if (request.StartsWith("STOR"))
                                {
                                    string filename = request.Substring(5);
                                    // Store file logic
                                    writer.WriteLine("150 File status okay; about to open data connection");
                                    writer.WriteLine("226 Closing data connection");
                                }
                                else if (request.StartsWith("RETR"))
                                {
                                    string filename = request.Substring(5);
                                    // Retrieve file logic
                                    writer.WriteLine("150 File status okay; about to open data connection");
                                    writer.WriteLine("226 Closing data connection");
                                }
                                else if (request.StartsWith("QUIT"))
                                {
                                    writer.WriteLine("221 Service closing control connection");
                                    break;
                                }
                                else
                                {
                                    writer.WriteLine("502 Command not implemented");
                                }
                            }
                          
                        }
                    });
                    Task.Run(async() => {
                        while (true)
                        {
                            await SyncFiles(sourceServer, destServer, username, password, sourcePath, destPath);
                            await Task.Delay(syncIntervalSeconds * 1000); // 等待指定的时间间隔
                        }
                    });
                }

            }


            return;
            if (App.isMaster != null)
            {
               
                var listXt = await SQLiteHelper.TableAsync<HeartEntity>().Where(x => x.IsLocal == "true").ToListAsync().ConfigureAwait(false);
                var xtFirst = listXt?.FirstOrDefault();
 
                if (xtFirst == null)
                {
                    return;

                }
                 
                if (!App.isMaster.Value)
                {//从机
                    if (string.IsNullOrEmpty(xtFirst.MasterHeartIPBind))
                    {
                        return;
                    }
                    await CreateTcpServer(xtFirst.HeartIP).ConfigureAwait(false);
               
                    await HandleFiles().ConfigureAwait(false);
              
                   
                }
                else
                { //主机
                    await CreateTcpClient(xtFirst.MasterHeartIPBind).ConfigureAwait(false);
                    await CreateFileListenServer().ConfigureAwait(false);
                }
            }
            return;
        }


        public static async Task SyncFiles(string sourceServer, string destServer, string username, string password, string sourcePath, string destPath)
        {
            try
            {
                using (var sourceClient = new System.Net.WebClient())
                {
                    sourceClient.Credentials = new System.Net.NetworkCredential(username, password);

                    using (var destClient = new System.Net.WebClient())
                    {
                        destClient.Credentials = new System.Net.NetworkCredential(username, password);

                        string[] sourceFiles = Directory.GetFiles(sourcePath);
                        string[] destFiles = Directory.GetFiles(destPath);

                        // 初始文件同步
                        foreach (string file in sourceFiles)
                        {
                            string fileName = Path.GetFileName(file);
                            string destFilePath = Path.Combine(destPath, fileName);

                            if (!destFiles.Contains(destFilePath))
                            {
                                await destClient.UploadFileTaskAsync(new Uri(destServer + "/" + fileName), "STOR", file);
                                Console.WriteLine($"File {fileName} synced to destination server.");
                            }
                        }

                        // 对比文件指纹并同步
                        foreach (string file in sourceFiles)
                        {
                            string fileName = Path.GetFileName(file);
                            string sourceFileHash = CalculateMD5(file);
                            string destFilePath = Path.Combine(destPath, fileName);

                            if (destFiles.Contains(destFilePath))
                            {
                                string destFileHash = CalculateMD5(destFilePath);

                                if (sourceFileHash != destFileHash)
                                {
                                    await destClient.UploadFileTaskAsync(new Uri(destServer + "/" + fileName), "STOR", file);
                                    Console.WriteLine($"File {fileName} synced to destination server.");
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {

                IsStart = false;
            }
          
        }

        public static string CalculateMD5(string filePath)
        {
            using (var md5 = MD5.Create())
            {
                using (var stream = File.OpenRead(filePath))
                {
                    byte[] hash = md5.ComputeHash(stream);
                    return BitConverter.ToString(hash).Replace("-", "").ToLower();
                }
            }
        }

        /// <summary>
        /// 处理同步的文件
        /// </summary>
        /// <returns></returns>
        public async Task HandleFiles() { 
            
        }

        //创建文件监听服务
        public static async Task CreateFileListenServer() {
            var list = await SQLiteHelper.TableAsync<FilesSyncManageEntity>().ToListAsync().ConfigureAwait(false);
            foreach (var item in list)
            {
                foreach (var file in fileSystemWatcherList)
                {
                    if (item.IsEnable == "是")
                    {
                        if (item.FilePath == file.Path)
                        {
                            continue;
                        }
                        else
                        {
                            string sourceDirectory = $@"{item.FilePath}";
                            FileSystemWatcher watcher = new FileSystemWatcher();
                            watcher.Path = sourceDirectory;

                            // 监控文件的改变类型
                            watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;

                            // 添加事件处理程序
                            watcher.Changed += OnChanged;
                            watcher.Created += OnChanged;
                            watcher.Deleted += OnChanged;
                            watcher.Renamed += OnRenamed;

                            // 开始监控
                            watcher.EnableRaisingEvents = true;
                            fileSystemWatcherList.Add(watcher);
                        }
                    }
                    else
                    {
                        foreach (var watcher in fileSystemWatcherList)
                        {
                            watcher.EnableRaisingEvents = false;
                        }
                    }
                
                }
                if (!fileSystemWatcherList.Any(x=>x.Path==item.FilePath&&item.IsEnable=="是"))
                {
                    string sourceDirectory = $@"{item.FilePath}";
                    FileSystemWatcher watcher = new FileSystemWatcher();
                    watcher.Path = sourceDirectory;

                    // 监控文件的改变类型
                    watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;

                    // 添加事件处理程序
                    watcher.Changed += OnChanged;
                    watcher.Created += OnChanged;
                    watcher.Deleted += OnChanged;
                    watcher.Renamed += OnRenamed;

                    // 开始监控
                    watcher.EnableRaisingEvents = true;
                    fileSystemWatcherList.Add(watcher);
                }
                if (item.IsEnable=="否")
                {
                    fileSystemWatcherList.RemoveAll(x => x.Path == item.FilePath);
                }
            }
            fileSystemWatcherList.RemoveAll(x => x.EnableRaisingEvents==false);
        }

        /// <summary>
        /// 创建从机文件服务
        /// 朱润来
        /// 2023年11月13日14:38:17
        /// </summary>
        /// <param name="IP"></param>
        /// <returns></returns>
        public async Task CreateTcpServer(string IP) {
            try
            {
                if (string.IsNullOrEmpty(IP))
                {
                    return;
                }
                //开启TCP服务端
                if (App.fileTcpClient == null)
                {
                    Task.Run(() => {
                        // 设置本机IP地址和端口号
                        IPAddress localIpAddress = IPAddress.Parse(IP);
                        int localPort = (ConfigurationManager.AppSettings["FilePort"]?.ToString() ?? "6602").ToInt();
                        TcpListener server = new TcpListener(localIpAddress, localPort);
                        server.Start();
                        // 等待从服务器连接
                        //TcpClient backupClient = server.AcceptTcpClient();
                        App.fileTcpClient = new TcpClient();
                        App.fileTcpClient = server.AcceptTcpClient();
                        while (true)
                        {
                            NetworkStream backupNetworkStream = App.fileTcpClient.GetStream();

                            // 读取要备份的文件信息
                            byte[] fileInfoBuffer = new byte[1024];
                            int fileInfoBytesRead = backupNetworkStream.Read(fileInfoBuffer, 0, fileInfoBuffer.Length);
                            string fileInfo = System.Text.Encoding.UTF8.GetString(fileInfoBuffer, 0, fileInfoBytesRead);
                            string[] fileDetails = fileInfo.Split(',');
                            string action = fileDetails[0];
                            string filePath = fileDetails[1];

                            // 处理文件备份操作
                            if (action == "Created" || action == "Changed" || action == "Rename")
                            {
                                // 读取文件内容并保存到本地
                                using (FileStream fileStream = File.Create(filePath))
                                {
                                    byte[] buffer = new byte[1024];
                                    int bytesRead;
                                    while ((bytesRead = backupNetworkStream.Read(buffer, 0, buffer.Length)) > 0)
                                    {
                                        fileStream.Write(buffer, 0, bytesRead);
                                    }
                                }

                                Console.WriteLine("File backed up successfully.");
                                LoggerHelper.Info($"File backed up successfully.->{action}:{filePath}", "FileSync");
                            }
                            else if (action == "Deleted")
                            {
                                // 删除本地文件
                                File.Delete(filePath);
                                Console.WriteLine("File deleted successfully.");
                                LoggerHelper.Info($"File deleted successfully.->{action}:{filePath}", "FileSync");
                            }
                        }
                        ThreadPool.QueueUserWorkItem(new WaitCallback(AcceptServerConnect), server);
                    });
                   

                }
            }
            catch (Exception ex)
            {
                LoggerHelper.Error(ex.Message, "文件检测");
            }
          
        }

        public async Task CreateTcpClient(string IP) {
            try
            {
                if (string.IsNullOrEmpty(IP))
                {
                    return;
                }
                if (App.fileTcpClient != null)
                {
                    return;
                }
                Task.Run(() => {
                    if (!NetWorkHelper.IsPingIP(IP))
                    {
                        return;
                    }
                    // 设置主服务器IP地址和端口号
                    IPAddress remoteIpAddress = IPAddress.Parse(IP);
                    int remotePort = (ConfigurationManager.AppSettings["FilePort"]?.ToString() ?? "6602").ToInt();

                    // 创建客户端Socket并连接到主服务器
                    App.fileTcpClient  = new TcpClient();
                    App.fileTcpClient.Connect(remoteIpAddress, remotePort);
                    while (true)
                    {

                        while (true)
                        {
                            NetworkStream backupNetworkStream = App.fileTcpClient.GetStream();

                            // 读取要备份的文件信息
                            byte[] fileInfoBuffer = new byte[1024];
                            int fileInfoBytesRead = backupNetworkStream.Read(fileInfoBuffer, 0, fileInfoBuffer.Length);
                            string fileInfo = System.Text.Encoding.UTF8.GetString(fileInfoBuffer, 0, fileInfoBytesRead);
                            string[] fileDetails = fileInfo.Split(',');
                            string action = fileDetails[0];
                            string filePath = fileDetails[1];

                            // 处理文件备份操作
                            if (action == "Created" || action == "Changed" || action == "Rename")
                            {
                                // 读取文件内容并保存到本地
                                using (FileStream fileStream = File.Create(filePath))
                                {
                                    byte[] buffer = new byte[1024];
                                    int bytesRead;
                                    while ((bytesRead = backupNetworkStream.Read(buffer, 0, buffer.Length)) > 0)
                                    {
                                        fileStream.Write(buffer, 0, bytesRead);
                                    }
                                }

                                Console.WriteLine("File backed up successfully.");
                                LoggerHelper.Info($"File backed up successfully.->{action}:{filePath}", "FileSync");
                            }
                            else if (action == "Deleted")
                            {
                                // 删除本地文件
                                File.Delete(filePath);
                                Console.WriteLine("File deleted successfully.");
                                LoggerHelper.Info($"File deleted successfully.->{action}:{filePath}", "FileSync");
                            }
                        }
                    }
                    ThreadPool.QueueUserWorkItem(new WaitCallback(AcceptClientConnect), App.fileTcpClient);
                });
              
            }
            catch (Exception ex)
            {
                LoggerHelper.Error(ex.Message, "文件检测");
            }
          

        
        }

        /// <summary>
        /// 线程池线程执行的接受客户端连接方法（从机主服务）
        /// </summary>
        /// <param name="obj">传入的Socket</param>
        private static void AcceptServerConnect(object obj)
        {
            try
            {
                var serverSocket = obj as TcpListener;
             
            }
            catch (Exception ex)
            {
                LoggerHelper.Error(ex.Message,"文件检测");
                App.fileTcpClient = null;
            }
        
          
        }

        private static async void AcceptClientConnect(object obj) {

            var serverSocket = obj as TcpClient;
            //App.fileTcpClient = serverSocket;
           
        }

        //// 文件改变事件处理程序
        //private static void OnChanged(object source, FileSystemEventArgs e)
        //{
        //    // 获取源文件路径
        //    string sourcePath = e.FullPath;
        //    // 获取目标文件路径
        //    string targetPath = Path.Combine(@"C:\TargetFolder", e.Name);

        //    // 如果是文件改变事件
        //    if (e.ChangeType == WatcherChangeTypes.Changed)
        //    {
        //        // 复制源文件到目标目录
        //        //File.Copy(sourcePath, targetPath, true);
        //        //Console.WriteLine("File {0} has been changed and synchronized.", e.Name);
        //        //文件改变
        //        SQLiteHelper.Add(new FilesTargetManageEntity
        //        {
        //            Name = e.Name,
        //            SourceFilePath = e.FullPath,
        //            TypeName = "Changed"
        //        }) ;

        //    }
        //    // 如果是文件创建事件
        //    else if (e.ChangeType == WatcherChangeTypes.Created)
        //    {
        //        // 复制源文件到目标目录
        //        //File.Copy(sourcePath, targetPath, true);
        //        //Console.WriteLine("File {0} has been created and synchronized.", e.Name);
        //        //文件新建
        //        SQLiteHelper.Add(new FilesTargetManageEntity
        //        {
        //            Name = e.Name,
        //            SourceFilePath = e.FullPath,
        //            TypeName = "Created"
        //        });

        //    }
        //    // 如果是文件删除事件
        //    else if (e.ChangeType == WatcherChangeTypes.Deleted)
        //    {
        //        // 删除目标目录中的文件
        //        //File.Delete(targetPath);
        //        //Console.WriteLine("File {0} has been deleted and synchronized.", e.Name);
        //        //文件删除

        //        SQLiteHelper.Add(new FilesTargetManageEntity
        //        {
        //            Name = e.Name,
        //            SourceFilePath = e.FullPath,
        //            TypeName = "Deleted"
        //        });
        //    }
        //}

        //// 文件重命名事件处理程序
        //private static void OnRenamed(object source, RenamedEventArgs e)
        //{
        //    // 获取源文件路径
        //    string sourcePath = e.OldFullPath;
        //    // 获取目标文件路径
        //    string targetPath = Path.Combine(@"C:\TargetFolder", e.Name);

        //    // 重命名目标目录中的文件
        //    //File.Move(sourcePath, targetPath);
        //    //Console.WriteLine("File {0} has been renamed and synchronized.", e.Name);
        //    //文件重命名

        //    SQLiteHelper.Add(new FilesTargetManageEntity
        //    {
        //        Name = e.Name,
        //        SourceFilePath = e.OldFullPath,
        //        TargetFilePath = e.FullPath,
        //        TypeName = "Renamed"
        //    });
        //}

        private static void OnChanged(object source, FileSystemEventArgs e)
        {
            // 获取文件操作类型
            string action = e.ChangeType.ToString();

            // 获取文件路径
            string filePath = e.FullPath;

            // 发送文件信息到主服务器
            SendFileInfoToMainServer(action, filePath);
        }

        // 当文件被重命名时触发
        private static void OnRenamed(object source, RenamedEventArgs e)
        {
            // 获取文件操作类型
            string action = "RENAME";

            // 获取文件路径
            string filePath = e.FullPath;

            // 发送文件信息到主服务器
            SendFileInfoToMainServer(action, filePath);
        }

        // 发送文件信息到主服务器
        private static void SendFileInfoToMainServer(string action, string filePath)
        {
            try
            {
                // 将文件操作类型和文件路径组合成字符串
                string fileInfo = action + "," + filePath;

                // 将文件信息转换为字节数组并发送到主服务器
                byte[] fileInfoBuffer = System.Text.Encoding.UTF8.GetBytes(fileInfo);
                NetworkStream networkStream = App.fileTcpClient.GetStream();
                networkStream.Write(fileInfoBuffer, 0, fileInfoBuffer.Length);

                // 如果是新增、修改或重命名操作，则发送文件内容到主服务器
                if (action == "Created" || action == "Changed" || action == "Rename")
                {
                    using (FileStream fileStream = File.OpenRead(filePath))
                    {
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            networkStream.Write(buffer, 0, bytesRead);
                        }
                    }
                }

                Console.WriteLine("File information sent to the main server.");
            }
            catch (Exception ex)
            {
                LoggerHelper.Error(ex.Message);
            }
        
        }
    }
}
